#include "Director.h"
#include "Logger.h"
#include "Scene.h"
#include "Timer.h"

namespace GeorgeLib
{

	Director::Director(void)
		: input(new Input)
	{
		currentScene = previousScene = NULL;
	}

	Director::~Director(void)
	{
		for (SceneMapIter i = scenes.begin(); i != scenes.end(); ++i)
			DELETE_PTR(i->second);

		currentScene = previousScene = NULL;

		DELETE_PTR(input);
	}

	void Director::Init(int argc, char **argv, const char* title, int width, int height)
	{
		glutInit(&argc, argv);
		glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH);

		int ScreenHeight = glutGet(GLUT_SCREEN_HEIGHT) / 2 - 300,
			ScreenWidth = glutGet(GLUT_SCREEN_WIDTH) / 2 - 400;
		// Resize the window to 800x600 and place it in the middle of the screen
		glutInitWindowSize(width, height);
		glutInitWindowPosition(ScreenWidth, ScreenHeight);

		glutCreateWindow(title);

		glutIdleFunc(SceneDisplay);
		glutDisplayFunc(SceneDisplay);
		glutKeyboardFunc(SceneKeyboardDown);
		glutKeyboardUpFunc(SceneKeyboardUp);
		glutSpecialFunc(SceneSpecialDown);
		glutSpecialUpFunc(SceneSpecialUp);
		glutMouseFunc(SceneMouse);
		glutMotionFunc(SceneMotion);
		glutPassiveMotionFunc(ScenePassiveMotion);

		glewInit();
	}

	void Director::SetWindowSize(int width, int height)
	{
		glutReshapeWindow(width, height);
		glViewport(0, 0, width, height);
		glutPostRedisplay();
	}

	void Director::AddScene(string name, Scene* scene, bool bRunScene)
	{
		if (scenes[name] == NULL)			// if there is not a scene with the same name
			scenes[name] = scene;

		if (bRunScene)
			ChangeScene(name);
	}

	void Director::ChangeScene(string name)
	{
		if (currentScene != NULL)			// if there is a Scene running
		{
			if (previousScene != NULL)		// if there is a previous Scene loaded
			{								// then make sure that it's cleared and its resources freed up
				previousScene->Drop();
				previousScene->Reset();
				previousScene->ResourceIsReady = false;
			}
			previousScene = currentScene;	// mark the current Scene as previous
		}

		currentScene = scenes[name];		// retrieve the requested Scene from the scenes

		if (!currentScene->ResourceIsReady)	// if the Scene has not loaded it's resources
		{
			currentScene->Load();			// then let it load its resources
			currentScene->ResourceIsReady = true;
		}
	}

	void Director::calcFPS(void)
	{
		framecount++;

		float delta = (float)currTime - (float)prevTime;

		if (delta > 1000)
		{
			fps = (float)framecount / (delta / 1000.0f);
			prevTime = currTime;
			framecount = 0;
		}
	}

	void GeorgeLib::SceneDisplay(void)
	{
		Director *dir = Director::getInstance();
		Scene* currentScene = dir->getCurrScene();
		if (currentScene == NULL) return;

		dir->currTime = Timer::getInstance()->GetTime();
		float delta = (float)dir->currTime - (float)dir->FPStimer;

		if (delta > 1000 / dir->fps)
		{
			dir->calcFPS();
			currentScene->Idle((1000 / dir->fps) / delta);

			glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
			glLoadIdentity();

			currentScene->Display();

			glutSwapBuffers();
			glutPostRedisplay();
		}
	}

	void GeorgeLib::SceneKeyboardDown(unsigned char key, int x, int y)
	{
		Director::getInstance()->input->KeyboardFunc(key, x, y);
	}

	void GeorgeLib::SceneKeyboardUp(unsigned char key, int x, int y)
	{
		Director::getInstance()->input->KeyboardUpFunc(key, x, y);
	}

	void GeorgeLib::SceneSpecialDown(int key, int x, int y)
	{
		Director::getInstance()->input->SpecialFunc(key, x, y);
	}

	void GeorgeLib::SceneSpecialUp(int key, int x, int y)
	{
		Director::getInstance()->input->SpecialUpFunc(key, x, y);
	}

	void GeorgeLib::SceneMouse(int button, int state, int x, int y)
	{
		Director::getInstance()->input->MouseFunc(button, state, x, y);
	}

	void GeorgeLib::SceneMotion(int x, int y)
	{
		Director::getInstance()->input->MotionFunc(x, y);
	}

	void GeorgeLib::ScenePassiveMotion(int x, int y)
	{
		Director::getInstance()->input->PassiveMotionFunc(x, y);
	}

} // namespace GeorgeLib